<!-- src/components/DigitalHuman.vue -->
<!-- pnpm add three 即可，不要其他人格的，包括@type/three,否则换进会报错 -->
<script setup lang="ts">
import { onMounted, shallowRef } from 'vue'
// @ts-ignore
import * as THREE from 'three'
// @ts-ignore
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
// @ts-ignore
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
// @ts-ignore
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader'

// 画布引用
const canvasRef = shallowRef<HTMLCanvasElement | null>(null)

// Three.js 对象
let scene: THREE.Scene
let camera: THREE.PerspectiveCamera
let renderer: THREE.WebGLRenderer
let controls: OrbitControls
let mixer: THREE.AnimationMixer | null = null

// 模型路径（放在 public/assets/models/ 下）
const modelPath = '/assets/models/37359f95-98fe-4dc8-b267-8d5e3efd82d8.glb'

// 初始化场景
const init = () => {
    if (!canvasRef.value) return

    // 创建场景
    scene = new THREE.Scene()
    scene.background = new THREE.Color(0x111111)

    // 相机
    camera = new THREE.PerspectiveCamera(
        45,
        canvasRef.value.clientWidth / canvasRef.value.clientHeight,
        0.1,
        1000
    )
    camera.position.set(0, 1.6, 4)

    // 渲染器
    renderer = new THREE.WebGLRenderer({ canvas: canvasRef.value, antialias: true })
    renderer.setSize(canvasRef.value.clientWidth, canvasRef.value.clientHeight)
    renderer.setPixelRatio(window.devicePixelRatio)
    renderer.outputEncoding = THREE.sRGBEncoding
    renderer.toneMapping = THREE.ACESFilmicToneMapping
    renderer.toneMappingExposure = 1.0

    // 环境光
    const ambientLight = new THREE.AmbientLight(0xffffff, 0.5)
    scene.add(ambientLight)

    // 平行光
    const directionalLight = new THREE.DirectionalLight(0xffffff, 1)
    directionalLight.position.set(5, 5, 5)
    scene.add(directionalLight)

    // 加载 HDR 环境贴图（更真实反射）
    // new RGBELoader().load('/assets/env.hdr', (texture) => {
    //     texture.mapping = THREE.EquirectangularReflectionMapping
    //     scene.environment = texture
    //     scene.background = texture
    // })

    // 控制器
    controls = new OrbitControls(camera, renderer.domElement)
    controls.target.set(0, 1.6, 0)
    controls.enableDamping = true
    controls.dampingFactor = 0.05

    // 地面网格（辅助参考）
    const gridHelper = new THREE.GridHelper(10, 20, 0x555555, 0x333333)
    scene.add(gridHelper)

    // 加载模型
    const loader = new GLTFLoader()
    loader.load(
        modelPath,
        (gltf: THREE.GLTF) => {
            const model = gltf.scene
            model.position.y = 0
            model.scale.set(1, 1, 1)
            scene.add(model)

            // 动画混合器
            if (gltf.animations.length > 0) {
                mixer = new THREE.AnimationMixer(model)
                const action = mixer.clipAction(gltf.animations[0]) // 播放第一个动画
                action.play()
            }
        },
        (progress: ProgressEvent) => {
            console.log(`模型加载中: ${Math.floor((progress.loaded / progress.total) * 100)}%`)
        },
        (error: ErrorEvent) => {
            console.error('模型加载失败:', error)
        }
    )

    // 窗口自适应
    window.addEventListener('resize', onWindowResize)
}

// 窗口调整
const onWindowResize = () => {
    if (!canvasRef.value) return
    camera.aspect = canvasRef.value.clientWidth / canvasRef.value.clientHeight
    camera.updateProjectionMatrix()
    renderer.setSize(canvasRef.value.clientWidth, canvasRef.value.clientHeight)
}

// 动画循环
const animate = () => {
    requestAnimationFrame(animate)

    // 更新控制器
    controls.update()

    // 更新动画
    if (mixer) {
        mixer.update(0.016) // 约 60fps
    }

    renderer.render(scene, camera)
}

// 组件挂载后初始化
onMounted(() => {
    init()
    animate()
})
</script>

<template>
    <div class="three-container">
        <canvas ref="canvasRef" class="three-canvas"></canvas>
    </div>
</template>

<style scoped>
.three-container {
    width: 100%;
    height: 100%;
    overflow: hidden;
    /* 防止滚动条 */
}

.three-canvas {
    display: block;
    width: 100% !important;
    height: 100% !important;
    border-radius: 10px;
}
</style>